﻿/********************************************************************************
 * Developed by Phil Tyler (http://www.laidbackcoder.co.uk)
 * 
 * Cryptosolic is Licensed under the GNU Lesser General Public License (LGPL)
 * http://cryptosolic.codeplex.com/license
 * *****************************************************************************/
using System.ComponentModel;
using System.Security.Cryptography;
using System.Text;
using Cryptosolic.Utilities;

namespace Cryptosolic.Security.Hashing
{
    /// <summary>
    /// Base Hashing Algorithm Class
    /// </summary>
    /// <remarks>
    /// Used only to provide Base Methods to Sub Classes - DO NOT instantiate directly
    /// </remarks>
    [Browsable(false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
    public abstract class HashingAlgorithm : IHashingAlgorithm
    {
        /// <summary>
        /// Hash Human Readable String
        /// </summary>
        /// <param name="data">Data to be Hashed</param>
        /// <returns>Hashed Data</returns>
        public CipherText HashData(string data)
        {
            // Convert a String to Byte[] and pass to the HashData(Byte[]) 
            // Method which should be overridden by sub class.
            return HashData(DataConverter.StringToBytes(data));
        }

       /// <summary>
        /// Hash Human Readable String
        /// </summary>
        /// <param name="data">Data to be Hashed</param>
        /// <param name="iterations">Number of times the Data will be Hashed</param>
        /// <returns>Hashed Data</returns>
        public CipherText HashData(string data, int iterations)
        {
            byte[] tempData = DataConverter.StringToBytes(data);

            for (int i = 0; i < iterations; i++)
            {
                tempData = HashData(tempData).ToBytes();
            }

            return new CipherText(tempData);
        }

        /// <summary>
        /// Hash Human Readable String
        /// </summary>
        /// <param name="data">Data to be Hashed</param>
        /// <returns>Hashed Data</returns>
        /// <remarks>
        /// This method will throw an Exception if not Overridden!
        /// </remarks>
        public abstract CipherText HashData(byte[] data);


        /// <summary>
        /// Hash a Human Readable Byte Array
        /// </summary>
        /// <param name="data">Data to be Hashed</param>
        /// <param name="iterations">Number of times the Data will be Hashed</param>
        /// <returns>Hashed Data</returns>
        public CipherText HashData(byte[] data, int iterations)
        {
            byte[] tempData = data;

            for (int i = 0; i < iterations; i++)
            {
                tempData = HashData(tempData).ToBytes();
            }

            return new CipherText(tempData);
        }

        /// <summary>
        /// Hash a Human Readable Byte Array
        /// </summary>
        /// <param name="data">Data to be Hashed</param>
        /// <param name="hashProvider">Hashing Algorithm used to compute the Hash</param>
        /// <returns>Hashed Data</returns>
        internal CipherText PerformHashOperation(byte[] data, HashAlgorithm hashProvider)
        {
            byte[] hash = hashProvider.ComputeHash(data);
            hashProvider.Clear();

            return new CipherText(hash);
        }
    }
}
